package repository

import (
	"JK-Junior-Go-Engineer-Camp/webook/internal/domain"
	"JK-Junior-Go-Engineer-Camp/webook/internal/repository/dao"
	"context"
	"github.com/ecodeclub/ekit/sqlx"
)

var ErrWaitingSMSNotFound = dao.ErrWaitingSMSNotFound

//go:generate mockgen -source=./async_sms.go -package=repomocks -destination=mocks/async_sms_mock.go AsyncSmsRepository
type AsyncSmsRepository interface {
	// Add 添加一个异步短信到数据库
	Add(ctx context.Context, domainAsyncSms domain.AsyncSms) error
	// PreemptWaitingSMS 抢占式发送一条等待中的异步短信
	// 抢占一个异步发送的消息，确保在非常多个实例的情况下，
	// 比如 k8s 部署了三个 pod，一个请求，只有一个实例能拿到
	PreemptWaitingSMS(ctx context.Context) (domain.AsyncSms, error)
	// ReportScheduleResult 更新异步短信状态（发送成功/失败）
	ReportScheduleResult(ctx context.Context, id int64, success bool) error
}

type asyncSmsRepository struct {
	dao dao.AsyncSmsDAO
}

func newAsyncSmsRepository(dao dao.AsyncSmsDAO) *asyncSmsRepository {
	return &asyncSmsRepository{dao: dao}
}

// Add 添加一个异步短信到数据库
func (a *asyncSmsRepository) Add(ctx context.Context, domainAsyncSms domain.AsyncSms) error {
	return a.dao.Insert(ctx, dao.AsyncSms{
		Config: sqlx.EncryptColumn[dao.SmsConfig]{
			Val: dao.SmsConfig{
				TplID:   domainAsyncSms.TplId,
				Args:    domainAsyncSms.Args,
				Numbers: domainAsyncSms.Numbers,
			},
			Valid: true,
		},
		RetryMax: domainAsyncSms.RetryMax,
	})
}

// PreemptWaitingSMS 抢占式发送等待中的异步短信
func (a *asyncSmsRepository) PreemptWaitingSMS(ctx context.Context) (domain.AsyncSms, error) {
	smsDao, err := a.dao.GetWaitingSMS(ctx)
	if err != nil {
		return domain.AsyncSms{}, err
	}
	return domain.AsyncSms{
		Id:       smsDao.Id,
		TplId:    smsDao.Config.Val.TplID,
		Numbers:  smsDao.Config.Val.Numbers,
		Args:     smsDao.Config.Val.Args,
		RetryMax: smsDao.RetryMax,
	}, nil
}

// ReportScheduleResult 更新异步短信状态（发送成功/失败）
func (a *asyncSmsRepository) ReportScheduleResult(ctx context.Context, id int64, success bool) error {
	if success {
		return a.dao.MarkSuccess(ctx, id)
	}
	return a.dao.MarkFailed(ctx, id)
}
